﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Scripting;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;

namespace DlrBasic.Parser.Ast
{
    class LogicalOperators: BinaryExpressionList
    {
        static int[] OperatorsKeywordIds = { Keywords.AndKeywordId, Keywords.OrKeywordId, 
                                         Keywords.XorKeywordId, Keywords.EqvKeywordId, Keywords.ImpKeywordId };
        static string[] OperatorMethods = { "And", "Or", "Xor", "Eqv", "Imp" };

        public LogicalOperators(SourceSpan span, DlrBasicExpression[] expressions, int[] operatorIds)
            : base(span, expressions, operatorIds)
        {
        }

        protected internal override Expression Generate(DlrBasicGenerator tg)
        {
            List<Expression> result = new List<Expression>();
            foreach (DlrBasicExpression expr in Expressions)
            {
                result.Add(expr.Generate(tg));
            }
            List<int> operators = new List<int>(this.OperatorIds);

            for (int j = 0; j < OperatorsKeywordIds.Length; j++)
            {
                int i = 0;
                while (i < operators.Count)
                {
                    if (operators[i] == OperatorsKeywordIds[j])
                    {
                        System.Reflection.MethodInfo method;
                        Expression converted1, converted2;

                        TypeConversionUtils.FindMethodAndConvertOperands(typeof(Runtime.DlrBasicMath),
                            OperatorMethods[j], result[i], result[i + 1],
                            out method, out converted1, out converted2);


                        Expression expr = Expression.Call(method, converted1, converted2);

                        operators.RemoveAt(i);
                        result.RemoveAt(i); result.RemoveAt(i);
                        result.Insert(i, expr);
                    }
                    else
                        i++;
                }
            }
            return result[0];
        }

    }
}
